package org.springframework.security.web;

import jakarta.servlet.Filter;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.log.LogMessage;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Dillon
 * @date 2024/7/6
 * @slogan 致敬大师 致敬未来的你
 * @desc security 默认的过滤器链匹配实现
 */
public final class DefaultSecurityFilterChain implements SecurityFilterChain {

	/**
	 * 日志对象
	 */
	private static final Log logger = LogFactory.getLog(DefaultSecurityFilterChain.class);

	/**
	 * 请求匹配器
	 */
	private final RequestMatcher requestMatcher;

	/**
	 * 需要经过的过滤器链列表
	 */
	private final List<Filter> filters;

	/**
	 * 构造函数
	 *
	 * @param requestMatcher 请求匹配器
	 * @param filters        过滤器链数组
	 */
	public DefaultSecurityFilterChain(RequestMatcher requestMatcher, Filter... filters) {
		this(requestMatcher, Arrays.asList(filters));
	}

	/**
	 * 构造函数
	 *
	 * @param requestMatcher 请求匹配器
	 * @param filters        过滤器链列表
	 */
	public DefaultSecurityFilterChain(RequestMatcher requestMatcher, List<Filter> filters) {
		// log记录
		if (filters.isEmpty()) {
			logger.debug(LogMessage.format("过滤器链为空，请求匹配器为 %s", requestMatcher));
		} else {
			List<String> filterNames = new ArrayList<>();
			for (Filter filter : filters) {
				filterNames.add(filter.getClass().getSimpleName());
			}
			String names = StringUtils.collectionToDelimitedString(filterNames, ", ");
			logger.debug(LogMessage.format("请求匹配器 %s 通过过滤器链为: %s", requestMatcher, names));
		}
		// 域赋值
		this.requestMatcher = requestMatcher;
		this.filters = new ArrayList<>(filters);
	}

	/**
	 * 获取亲求匹配器
	 *
	 * @return 请求匹配器
	 */
	public RequestMatcher getRequestMatcher() {
		return this.requestMatcher;
	}

	/**
	 * 获取过滤器链
	 *
	 * @return 过滤器链
	 */
	@Override
	public List<Filter> getFilters() {
		return this.filters;
	}

	/**
	 * 匹配当前请求是否符合过滤条件
	 * 委托给请求匹配器来完成任务
	 *
	 * @param request 请求对象
	 * @return 是否符合条件
	 */
	@Override
	public boolean matches(HttpServletRequest request) {
		return this.requestMatcher.matches(request);
	}

	/**
	 * toString
	 *
	 * @return 序列化字符串
	 */
	@Override
	public String toString() {
		return this.getClass().getSimpleName() + " [RequestMatcher=" + this.requestMatcher + ", Filters=" + this.filters
				+ "]";
	}

}
